<template>
  <div class="app-container">
    <!-- 条件查询区域开始 -->
    <div class="search-container">
      <el-form ref="queryFormRef" :model="queryParams" :inline="true">
        <el-row>
          <el-col :span="6">
            <el-form-item :label="$t('sysMenu.module')" prop="moduleId">
              <el-select
                v-model="queryParams.moduleId"
                :placeholder="$t('sysMenu.moduleRequired')"
                class="!w-[203px]"
                clearable
                @change="tableHooks.handleQuery()"
              >
                <el-option
                  v-for="item in moduleLists"
                  :key="item.moduleId"
                  :label="item.moduleName"
                  :value="item.moduleId"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item :label="$t('sysMenu.name')" prop="likeResourceName">
              <el-input
                v-model="queryParams.likeResourceName"
                :placeholder="$t('sysMenu.nameRequired')"
                class="!w-[203px]"
                clearable
                @keyup.enter="tableHooks.handleQuery()"
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item :label="$t('sysMenu.status')" prop="hidden">
              <el-select
                v-model="queryParams.hidden"
                :placeholder="$t('sysMenu.statusRequired')"
                clearable
                class="!w-[203px]"
              >
                <el-option :label="$t('common.show')" :value="false" />
                <el-option :label="$t('common.hide')" :value="true" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item class="search-btn">
              <el-button type="primary" @click="tableHooks.handleQuery()">
                {{ $t("common.search") }}
              </el-button>
              <el-button @click="tableHooks.resetQuery()">{{
                $t("common.reset")
              }}</el-button>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div class="clear"></div>
    </div>
    <!-- 条件查询区域结束 -->

    <el-card shadow="never" class="table-container">
      <!-- 按钮开始 -->
      <template #header>
        <el-row justify="space-between">
          <el-col :span="17">
            <el-button
              v-hasPerm="['rbac:resource:add']"
              type="primary"
              @click="handleAdd(undefined)"
            >
              {{ $t("common.add") }}
            </el-button>
            <el-button
              v-hasPerm="['rbac:resource:delete']"
              type="primary"
              @click="tableHooks.deleteRecords()"
            >
              {{ $t("common.batchDelete") }}
            </el-button>
          </el-col>
          <el-col :span="7" class="container-float">
            <el-button
              v-hasPerm="['rbac:resource:import']"
              class="dropdown-left"
              plain
              type="primary"
              @click="uploadVisible = true"
            >
              {{ $t("common.import") }}
            </el-button>
            <el-button
              v-hasPerm="['rbac:resource:export']"
              class="dropdown-left"
              plain
              type="primary"
              @click="handleExport('', t('sysMenu.exportName'))"
            >
              {{ $t("common.export") }}
            </el-button>
            <jmash-column-select
              v-model="tableLabel"
              label-name="rbac/rbac-resource"
            />
          </el-col>
        </el-row>
      </template>
      <!-- 按钮结束 -->
      <!-- 表格开始 -->
      <jmash-table
        ref="multipleTableRef"
        row-key="resourceId"
        height="calc(100vh - 285px)"
        :list-loading="listLoading"
        :data="tableData"
        :table-label="tableLabel"
        @selection-change="tableSelected"
        @sort-change="handleSort"
        @scroll="handleScroll"
        lazy
        :load="handleLoad"
      >
        <!-- 资源名称 -->
        <template #name="scope">
          <svg-icon :icon-class="scope.data.row.icon" />
          <span style="padding-left: 5px">{{
            scope.data.row.resourceName
          }}</span>
        </template>
        <template #menuType="scope">
          <span>
            {{
              Dict.resourceTypeEnum.getEnumValue(scope.data.row.resourceType)
            }}
          </span>
        </template>
        <!-- 状态 -->
        <template #status="scope">
          <el-tag v-if="scope.data.row.hidden === false" type="success">
            {{ $t("common.show") }}
          </el-tag>
          <el-tag v-else type="danger">{{ $t("common.hide") }}</el-tag>
        </template>
        <!-- 排序 -->
        <template #sort="scope">
          <el-icon size="16" @click="handleMove(scope.data.row, false)">
            <Bottom />
          </el-icon>
          <el-icon size="16" @click="handleMove(scope.data.row, true)">
            <Top />
          </el-icon>
        </template>
        <template #operation="scope">
          <span
            v-hasPerm="['rbac:resource:update']"
            class="el-button-color"
            @click="handleEdit(scope.data.row)"
          >
            {{ $t("common.edit") }}
          </span>
          <span
            v-hasPerm="['rbac:resource:delete']"
            class="el-button-color dropdown-left"
            @click="handleDelete(scope.data.row)"
          >
            {{ $t("common.delete") }}
          </span>
          <el-dropdown class="dropdown-left">
            <span class="el-dropdown-link">
              {{ $t("common.more") }}
              <el-icon class="el-icon--right">
                <arrow-down />
              </el-icon>
            </span>
            <template #dropdown>
              <el-dropdown-menu>
                <div v-hasPerm="['rbac:resource:add']">
                  <el-dropdown-item @click="handleAdd(scope.data.row)">
                    {{ $t("common.add") }}
                  </el-dropdown-item>
                </div>
                <div v-hasPerm="['rbac:resource:export']">
                  <el-dropdown-item
                    @click="
                      handleExport(
                        scope.data.row.resourceId,
                        scope.data.row.resourceName,
                      )
                    "
                  >
                    {{ $t("common.export") }}
                  </el-dropdown-item>
                </div>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </template>
      </jmash-table>
    </el-card>
    <resource-edit
      v-if="dialog.visible"
      v-model="dialog.visible"
      :title="dialog.title"
      :entity-key="entityKey"
      width="1000px"
      @reload="handleReload"
    />
    <import-upload
      v-if="uploadVisible"
      :upload-visible="uploadVisible"
      :template-title="$t('sysMenu.templateDownload')"
      @template-down="tableHooks.downloadTemplate(t('sysMenu.name'))"
      @import-events="importExcel"
      @upload-closed="uploadClosed"
    />
  </div>
</template>
<script setup lang="ts">
import { type Ref, ref, reactive, nextTick } from "vue";
import {
  type TableColumn,
  type TableSort,
  type DialogRef,
  useTableHooks,
} from "jmash-core";
import { useI18n } from "vue-i18n";
const { t } = useI18n();

import { Dict } from "@/api/system/index";
import type {
  ResourceReq,
  ResourceModel,
  ResourceParam,
  ResourceImportReq,
  ResourceExportReq,
} from "@/api/system/menu/types";
import { moduleApi } from "@/api/system/module/index";
import { resourceApi } from "@/api/system/menu/index";
import { saveAs } from "file-saver";

import resourceEdit from "./edit.vue";
import { Constant } from "@/constant";
import { timelineItemProps } from "element-plus";
const queryParams = ref<ResourceReq>({
  resourceId: "",
  parentId: Constant.DEFAULT_ID,
});
const moduleLists = ref([] as Array<any>);

const tableLabel: Ref<TableColumn[]> = ref([
  {
    label: "sysMenu.name",
    prop: "resourceName",
    slotName: "name",
    columnType: "slot",
    isColumn: true,
    minWidth: "300",
  },
  {
    label: "sysMenu.type",
    width: "90",
    prop: "resourceType",
    slotName: "menuType",
    columnType: "slot",
    isColumn: true,
  },
  {
    label: "sysMenu.resourceCode",
    width: "150",
    prop: "resourceCode",
    isColumn: true,
  },
  {
    label: "sysMenu.url",
    width: "150",
    prop: "url",
    isColumn: true,
  },
  {
    label: "sysMenu.status",
    width: "90",
    prop: "hidden",
    columnType: "slot",
    slotName: "status",
    isColumn: true,
  },
  {
    label: "sysMenu.sort",
    width: "80",
    columnType: "slot",
    slotName: "sort",
    isColumn: true,
  },
  {
    label: "common.operate",
    width: "160",
    columnType: "slot",
    slotName: "operation",
    fixed: "right",
    isColumn: true,
  },
]);
const dialog = reactive<DialogRef>({
  visible: false,
  title: "",
});
const uploadVisible = ref(false);

const { tableHooks, multipleTableRef, queryFormRef, listLoading, tableData } =
  useTableHooks(t, resourceApi, queryParams);

function queryResourceData() {
  moduleApi.moduleList().then(({ data }) => {
    moduleLists.value = data.results;
  });
}

function tableSelected(value: ResourceModel[]) {
  tableHooks.selectionRows.value = value;
}

// 导入Excel.
function importExcel(val: ResourceImportReq) {
  val.updateMask = "";
  tableHooks.importExcel(val).then(() => {
    uploadVisible.value = false;
  });
}

// 关闭导入弹框
function uploadClosed() {
  uploadVisible.value = false;
}

let entityKey = reactive<ResourceParam>({});
const currentRow = ref<ResourceModel>({} as ResourceModel);
// 新增
function handleAdd(row: ResourceModel | undefined) {
  entityKey = reactive<ResourceParam>({});
  if (row) {
    currentRow.value = row;
    entityKey.parentId = row.resourceId;
    entityKey.moduleId = row.moduleId;
  }
  dialog.title = t("common.add");
  dialog.visible = true;
}

// 编辑
function handleEdit(row: ResourceModel) {
  entityKey.resourceId = row.resourceId;
  dialog.title = t("common.edit");
  dialog.visible = true;
}

// 处理排序
function handleSort(sort: TableSort) {
  tableHooks.handleSort(sort.prop, sort.order);
}

//导出
function handleExport(resourceId: string | undefined, name: string) {
  const temData = {
    req: { resourceId: resourceId },
  } as ResourceExportReq;
  resourceApi.exportExcel(temData).then(({ data }) => {
    const blob = new Blob([data], {
      type: "application/octet-stream",
    });
    saveAs(blob, name + ".xlsx");
  });
}

// 排序
const handleMove = (row: ResourceModel, up: boolean) => {
  resourceApi.move({ resourceId: row.resourceId }, up).then((res) => {
    if (res.status === 200) {
      !handleReloadChildren(row.parentId as string) && tableHooks.handleQuery();
    }
  });
};

// 删除
const handleDelete = (row: ResourceModel) => {
  ElMessageBox.confirm(t("common.confirmDelete"), t("common.delete"), {
    cancelButtonText: t("common.cancel"),
    confirmButtonText: t("common.confirm"),
    type: "warning",
  })
    .then(() => resourceApi.delete({ resourceId: row.resourceId }))
    .then((res) => {
      if (res.status === 200) {
        ElMessage({
          message: t("common.deleteSuccess"),
          type: "success",
        });
        !handleReloadChildren(row.parentId as string) &&
          tableHooks.handleQuery();
      }
    });
};

// 存储懒加载的树形数据
const lazyData = new Map();
// 表格懒加载
const handleLoad = (
  row: ResourceModel,
  treeNode: unknown,
  resolve: (data: ResourceModel[]) => void,
) => {
  lazyData.set(row.resourceId, { row, treeNode, resolve });
  resourceApi
    .findPage({ ...queryParams.value, parentId: row.resourceId })
    .then(({ data }) => {
      data.results.forEach((item) => {
        item.hasChildren = !item.isLeaf;
      });
      resolve(data.results);
      if (!data.results.length) {
        const { store } = multipleTableRef.value.refs();
        store.states.lazyTreeNodeMap.value[row.resourceId] = [];
      }
    });
};

// 新增修改组件传递事件触发渲染
const handleReload = (row: ResourceModel) => {
  if (!row.parentId || row.parentId === Constant.DEFAULT_ID) {
    tableHooks.handleQuery();
    return;
  }
  if (currentRow.value.parentId) {
    !handleReloadChildren(currentRow.value.parentId as string) &&
      tableHooks.handleQuery();
    currentRow.value = {} as ResourceModel;
  }

  handleReloadChildren(row.parentId as string);
};

// 重新渲染子级
const handleReloadChildren = (id: string): boolean => {
  if (!lazyData.has(id) || !id) return false;
  const { row, treeNode, resolve } = lazyData.get(id);
  handleLoad(row, treeNode, resolve);
  return true;
};

// 滚动事件
function handleScroll({ scrollTop }: { scrollTop: number }) {
  if (!scrollTop) return;
  const tableBody = multipleTableRef.value.refs()?.$el;

  const tableWrapper = tableBody.querySelector(".el-table__body-wrapper");
  const scrollbar = tableBody.querySelector(".el-scrollbar__view");

  if (scrollbar.scrollHeight - scrollTop - tableWrapper.clientHeight <= 50) {
    if (index >= concatData.length) return;
    tableData.value = tableData.value.concat(concatData[index]);
    index++;
  }
}

let concatData: ResourceModel[][] = [];
let index = 1;

tableHooks.getList = function () {
  listLoading.value = true;
  concatData = [];
  index = 1;
  resourceApi.findPage(queryParams.value).then((res) => {
    res.data.results.forEach((item) => {
       item.hasChildren = !item.isLeaf;
    });
    for (let i = 0; i < res.data.results.length; i += 20) {
      concatData.push(res.data.results.slice(i, i + 20));
    }
    concatData[0] && (tableData.value = concatData[0]);
    listLoading.value = false;
  });
};

queryResourceData();
// 查询数据.
tableHooks.getList();
</script>
